/*
	The MIT License

	Copyright (c) 2010 IFMO/GameDev Studio

	Permission is hereby granted, free of charge, to any person obtaining a copy
	of this software and associated documentation files (the "Software"), to deal
	in the Software without restriction, including without limitation the rights
	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
	copies of the Software, and to permit persons to whom the Software is
	furnished to do so, subject to the following conditions:

	The above copyright notice and this permission notice shall be included in
	all copies or substantial portions of the Software.

	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
	THE SOFTWARE.
*/

#pragma once


class	ERScene;

/*-----------------------------------------------------------------------------
	Surface shader itself :
-----------------------------------------------------------------------------*/

enum ERSShaderTech_t {
		RS_TECH_DEFERRED	=0,
		RS_TECH_EMISSION	,
		RS_TECH_DISTORTION	,
		RS_TECH_TRANSLUCENT	,
		RS_TECH_SHADOWMAP	,
		RS_TECH_WIREFRAME	,
		RS_TECH_DEBUG		,		
		RS_TECH_MAX			,
	};

const uint	RS_MAX_HW_JOINTS = 50;

struct ERSShaderCore_t {
		bool	is_solid;			//	output to G-Buffer
		bool	is_emissive;		//	output to emission, Glow
		bool	is_reflective;		//	output to emission, Reflection
		bool	is_distortive;		//	output to dUdV buffer, Distortion
		bool	is_translucent;		//	
		bool	is_pixkill;			//	need to kill pixels?

		int		detail_type;		//	0 - no detail, 1 - detail diffuse, 2 - detail normalmap
		float	detail_scale;		//	
		
		float	reflect_fresnel;	//	0 - no fresnel
		float	emission_scale;		//	1 - by default
		
		IPxTexture	tex_diffuse;		
		IPxTexture	tex_specular;		
		IPxTexture	tex_normals;		
		IPxTexture	tex_emission;		
		IPxTexture	tex_detail;		
		IPxTexture	tex_environment;	
		IPxTexture	tex_reflect_mask;
	};



class ERSShader : public IRSShader {
	public:
							ERSShader		( ERScene *scene, lua_State *L );
							~ERSShader		( void );
		virtual bool		Setup			( void );
		virtual EString		Name			( void ) const { return name; }

		bool				IsTechRequired	( ERSShaderTech_t tech ) const { return required_techs[ tech ]; }
		ERSShaderCore_t		*GetCore		( void ) { return &core; }	

	protected:	
		EString	name;
		ERScene	*scene;
		bool	is_textures_loaded;
		bool	required_techs[ RS_TECH_MAX ];
		
		ERSShaderCore_t	core;
		
		EString	path_diffuse;			//	RGB - diffuse,	A - transparency/kill
		EString	path_specular;			//	RGB - specular,	A - spec power
		EString	path_normals;			//	RGB - normals,	A - detail mask
		EString	path_emission;			//	RGB - emission,	A - reflection mask
		EString	path_detail;			//	RGBA - affection
		EString	path_environment;		//	RGB - environment texture
		EString	path_reflect_mask;		//	RGB - reflection mask texture
	};


/*-----------------------------------------------------------------------------
	Scene shader system :
-----------------------------------------------------------------------------*/

class	ERSShadingSystem : public ICoreObject {
	public:
						ERSShadingSystem		( ERScene *scene );
						~ERSShadingSystem		( void );

		IPxRSShader		GetShader				( const EString name );
		void			ReloadShaders			( void );

		bool			BeginShading			( ERSShaderTech_t tech );
		bool			SetupShading			( ERSShader *shader );
		void			EndShading				( void );
		
		void			SetWorldMatrix			( const EMatrix4 &w );
		void			SetViewMatrix			( const EMatrix4 &v, EVec4 view_pos ); 
		void			SetProjMatrix			( const EMatrix4 &p );

		void			SetSkinningEnabled		( bool enable );
		void			SetJoints				( IPxTriMesh mesh );
		
	protected:
		static int		ReloadSurfaceShaders	( lua_State *L );
		static int		DefineShader			( lua_State *L );

		ERScene				*scene;	
		vector<IPxRSShader>	scene_shaders;
		
		//	some states to be passed to effect :
		EMatrix4	matrix_world;
		EMatrix4	matrix_view;
		EMatrix4	matrix_proj;
		EMatrix4	matrix_wvp;
		bool		skinning_enabled;

		//	effect's stuff :		
		ID3DXEffect			*effect;
		ERSShaderTech_t		current_tech;
		
		//	techniques and passes :
		D3DXHANDLE	techniques[ RS_TECH_MAX ];
		
		//	common parameters :
		D3DXHANDLE	p_matrix_view;
		D3DXHANDLE	p_matrix_world;
		D3DXHANDLE	p_matrix_proj;
		D3DXHANDLE	p_matrix_wvp;
		D3DXHANDLE	p_matrix_world_tbn;
		D3DXHANDLE	p_view_position;
		
		D3DXHANDLE	p_is_skinned;
		D3DXHANDLE	p_joint_matrix;

		//	shader core parameters :		
		D3DXHANDLE	p_is_solid;		
		D3DXHANDLE	p_is_emissive;		
		D3DXHANDLE	p_is_reflective;	
		D3DXHANDLE	p_is_distortive;	
		D3DXHANDLE	p_is_translucent;	
		D3DXHANDLE	p_is_pixkill;		
		D3DXHANDLE	p_detail_type;	
		D3DXHANDLE	p_detail_scale;
		D3DXHANDLE	p_reflect_fresnel;
		D3DXHANDLE	p_emission_scale;
			
		D3DXHANDLE	p_tex_diffuse;		
		D3DXHANDLE	p_tex_specular;		
		D3DXHANDLE	p_tex_normals;		
		D3DXHANDLE	p_tex_emission;		
		D3DXHANDLE	p_tex_detail;		
		D3DXHANDLE	p_tex_environment;	
	};
	